<?php
pathnode::heritage('filenode',2);
/**
*
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class fileNode extends pathNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function filenode($path) {
		$this->__construct($path);
	}/**/
	
	/**
	*
	* @access
	* /
	function __construct($path) {
		parent::__construct($path);
		if (!$this->exists)	{
			touch($path);
		}
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* detects if path applies to self class
	* @param
	* @access public
	* @return bool
	*/
	public function selfDetector($path) {
		return is_file($path);
	}/**/
	
	/**
	* read some bytes.
	* Reads all content if bytes is not provided. From offset, if provided, else current offset.
	* @param int bytes optional 1mo by default
	* @param int offset optional uses current offset by default
	* @access public
	* @return mixed file content
	*/
	public function read($bytes=1048576, $offset=NULL) {
		/*if (!$this->isReadable()) {
			trigger_error('filenode::read : file'.$this->path.' is not readable',E_USER_NOTICE);
			return false;
		}*/
		// getting handle
		if (!$handle=&$this->handle()) {
			trigger_error('filenode::read could not read '.$this->path);
			return false;
		}
		// setting offset if necessary
		$this->offset($offset);
		return fread($handle,$bytes);
	}/**/
	
	/**
	* write some data.
	* From offset, if provided, else current offset.
	* @param mixed $content
	* @param int offset optional. uses current offset if omitted
	* @access public
	* @return bool
	*/
	public function write($content, $offset=NULL) {
		// is file writable
		/*if (!$this->isWritable()) {
			trigger_error('filenode::write : file '.$this->path.' is not writable',E_USER_NOTICE);
			return false;
		}*/
		// getting handle
		if (!$handle=&$this->handle())
			return false;
		// setting offset if necessary
		$this->offset($offset);
		return fwrite($handle,$content);
	}/**/
	
	/**
	* erase from offset
	* @param int offset
	* @return bool
	*/
	public function erase($offset=NULL) {
		// getting handle
		if (!$handle=&$this->handle())
			return false;
		// setting offset if necessary
		//$oldOffset=$this->offset();
		$from=$this->offset($offset);
		// echo $from;
		$ok=ftruncate($handle, $from);
		// echo $this->offset();
		// $this->offset($offset);
		return $ok;
	}
	
	/**
	* returns and edventually sets handle’s offset.
	* @param int offset optional sets new offset
	* @access public
	* @return int current offset
	*/
	public function offset($offset=NULL,$whence=NULL) {
		// getting file handle
		if (!$handle=&$this->handle())
			return false;
		// is new offset provided
		if (is_int($offset)) {
			// setting whence 
			switch ($whence) {
				case SEEK_CUR: // new offset is from current position
				case SEEK_END: // new offset is from the end
					break;
				default: // new offset is from start
					$whence=SEEK_SET;
			}
			// trying to set new offset
			fseek($handle,$offset,$whence);
		}
		return ftell($handle);
	}/**/
	
	/**
	* sets offset to end of file
	*/
	public function toEnd() {
		return $this->offset(0,SEEK_END);
	}
	/**
	* sets offset to start of file
	*/
	public function toStart() {
		return $this->offset(0,SEEK_SET);
	}
	
	/**
	* destroy file
	* @param
	* @access public
	* @return 
	*/
	public function delete() {
		if (!$this->exists) return true;
		$this->exists=!unlink($this->path);
		return !$this->exists;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	public function move($path) {
		
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return int
	*/
	public function size() {
		return $this->exists()?filesize($this->path):0;
	}/**/
	
	/**
	* does the file exists ?
	* @param
	* @access public
	* @return bool
	*/
	public function exists() {
		return file_exists($this->path);
	}/**/
	
	/**
	* returns md5 hash of the file's content
	* @param
	* @access public
	* @return 
	*/
	public function md5() {
		return md5_file($this->path);
	}/**/
	
	/**
	* is the file readable ?
	* @access public
	* @return bool
	*/
	public function isReadable() {
		if (PHP_OS=='WINNT')
			return true;
		//clearstatcache();
		return is_readable($this->path);
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	public function isWritable() {
		if (PHP_OS=='WINNT')
			return true;
		return is_writable($this->path);
	}/**/
	
	/**
	* executes a regex search on self name, returns results array
	* @param
	* @access public
	* @return array
	*/
	public function regexSelfName($regex) {
		if (!ereg($regex,$this->basename,$results))
			return false;
		return $results;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
	

/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	//var $type='file';
	protected $_handle; // file's handle
	protected $mode; // handle's mode
	protected $_offset=0; // handler position, in octets since start
	// var $_mode; // current fopen mode
	// var $content; // file content 
	// var $size;
	//var $_sync=false;
	// var $_sync_mode=false; // if file content has to be saved/read every time
/*------------------------------------------------------------------------------
                                                               protected methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function setInfo($path) {
		parent::setinfo($path);
		if ($this->exists) 
			$this->size=filesize($this->relative_path);
		else
			$this->size=0;
	}/**/
	
	/**
	* returns file handle
	* @access public
	* @param string $mode
	* @return resource file hande
	*/
	protected function & handle($mode=null) {
		if (!$this->_handle) {
			// defining default mode if required
			if (is_null($mode)) {
				switch (true) {
					case $this->exists() and $this->isWritable():
						$mode='r+';
						break;
					case $this->exists():
						$mode='r';
						break;
					default:
						$mode='w+';
				}
			}
			// opening in requested mode
			if ($this->_handle=fopen($this->path,$mode)) {
				$this->mode=$mode;
				// trigger_error('opened '.$this->path.' in mode '.$mode);
			} else
				trigger_error('failed to open '.$this->path.' in mode '.$mode);
			// echo wakapi::vardump($this);
		}
		return $this->_handle;
	}/**/
	

	
	/**
	* return file's handle
	* @param
	* @access public
	* @return 
	* /
	function & _getHandle($rewind=false) {
		if ($rewind)
			$this->_closeHandle();
		if (!$this->_handle) {
			if ($this->exists)
				$this->_handle=fopen($this->path,'r+');
			else
				$this->_handle=fopen($this->path,'w+');
		}
		return $this->_handle;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
}
?>
